﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.Web;
using System.Globalization;
using System.Reflection;

namespace nanobot {

    public class FieldReference<T> {
        private object ownerObject;
        private FieldInfo fieldInfo;

        public FieldReference ( object ownerObject, string fieldName ) {
            this.ownerObject = ownerObject;
            this.fieldInfo = ownerObject.GetType().GetField( fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance );
        }

        public FieldReference ( object ownerObject, FieldInfo fieldInfo ) {
            this.ownerObject = ownerObject;
            this.fieldInfo = fieldInfo;
        }

        public T Value {
            get { return ( T ) this.fieldInfo.GetValue( this.ownerObject ); }
            set { this.fieldInfo.SetValue( this.ownerObject, value ); }
        }
    }


    public static class HelperClass {
        private static CultureInfo culture = new CultureInfo( "en-us" );

        public static DateTime FromUnixTime ( long unixTime ) {
            var epoch = new DateTime( 1970, 1, 1, 0, 0, 0, DateTimeKind.Utc );
            return epoch.AddSeconds( unixTime );

        }

        public static string CurrentUnixTime () {
            TimeSpan t = DateTime.UtcNow - new DateTime( 1970, 1, 1 );
            return ( ( long ) t.TotalSeconds ).ToString();

        }

        public static long ToUnixTime ( this DateTime date ) {
            var epoch = new DateTime( 1970, 1, 1, 0, 0, 0, DateTimeKind.Utc );
            return Convert.ToInt64( ( date.ToUniversalTime() - epoch ).TotalSeconds );
        }

        public static string GeneratePostDataString ( string command ) {
            string data = UrlEncode( new Dictionary<string, string> {
                                {"command", command},
                                {"nonce", CurrentUnixTime()}
                            } );

            return data;
        }

        public static string UrlEncode ( IDictionary<string, string> parameters ) {
            var sb = new StringBuilder();
            foreach ( var val in parameters ) {
                // add each parameter to the query string, url-encoding the value.
                sb.AppendFormat( "{0}={1}&", val.Key, HttpUtility.UrlEncode( val.Value ) );
            }
            sb.Remove( sb.Length - 1, 1 ); // remove last '&'
            return sb.ToString();
        }

        public static string SendPost ( string url, string postData, string api_key, string secret ) {
            string webpageContent = string.Empty;

            try {
                string signed_postData = SignPost( secret, postData );
                byte[] byteArray = Encoding.UTF8.GetBytes( postData );

                HttpWebRequest webRequest = ( HttpWebRequest ) WebRequest.Create( url );
                webRequest.Method = "POST";
                webRequest.Headers.Add( "key", api_key );
                webRequest.Headers.Add( "Sign", signed_postData );
                webRequest.ContentType = "application/x-www-form-urlencoded";
                //webRequest.ContentType = "text/x-gwt-rpc; charset=utf-8";
                webRequest.ContentLength = byteArray.Length;

                using ( Stream webpageStream = webRequest.GetRequestStream() ) {
                    webpageStream.Write( byteArray, 0, byteArray.Length );
                }

                using ( HttpWebResponse webResponse = ( HttpWebResponse ) webRequest.GetResponse() ) {
                    using ( StreamReader reader = new StreamReader( webResponse.GetResponseStream() ) ) {
                        webpageContent = reader.ReadToEnd();
                    }
                }
            } catch ( Exception ex ) {
                throw ex;
            }

            return webpageContent;
        }

        public static string SignPost ( string secret, string post_data ) {
            System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
            using ( HMACSHA512 hamc = new HMACSHA512( StringToByteArray( secret ) ) ) {
                byte [] post_data_bytes = encoding.GetBytes( post_data );
                byte [] hash_postData = hamc.ComputeHash( post_data_bytes );

                return ByteToString( hash_postData );
            }
        }

        public static byte[] StringToByteArray ( String hex ) {
            if ( ( hex.Length % 2 ) == 1 ) hex += '0';
            byte[] bytes = new byte[hex.Length / 2];
            for ( int i = 0; i < hex.Length; i += 2 ) {
                bytes[i / 2] = System.Convert.ToByte( hex.Substring( i, 2 ), 16 );
            }
            return bytes;
        }

        public static string ByteToString ( byte[] buff ) {
            string sbinary = "";

            for ( int i = 0; i < buff.Length; i++ ) {
                sbinary += buff[i].ToString( "x2" ); // hex format
            }

            return ( sbinary );
        }

        public static DateTime getDateTimeFromJsonString ( string datetime_string ) {
            string[] date = datetime_string.Split( new char[] { ':', '-', ' ' }, StringSplitOptions.RemoveEmptyEntries );
            DateTime datetime = new DateTime(
                            int.Parse( date[0] ),
                            int.Parse( date[1] ),
                            int.Parse( date[2] ),
                            int.Parse( date[3] ),
                            int.Parse( date[4] ),
                            int.Parse( date[5] )
                            );

            return datetime;
        }

        public static double Parse_double ( string number ) {
            return double.Parse( number, culture );
        }

        public static int Parse_int ( string number ) {
            return int.Parse( number, culture );
        }

        public static float Parse_float ( string number ) {
            return float.Parse( number, culture );
        }

        public static int[] indexOfAny_String ( string str, string s ) {
            List<int> index = new List<int>();
            int temp;
            bool found;

            for ( int i = 0; i < str.Length; i++ ) {
                temp = -1;
                found = false;

                if ( ( i + s.Length ) >= str.Length ) {
                    break;
                }

                if ( str[i] == s[0] ) {
                    temp = i;

                } else {
                    continue;
                }

                for ( int j = 1; j < s.Length; j++ ) {
                    if ( str[i + j] != s[j] ) {
                        found = false;
                        break;
                    }
                    found = true;
                }

                if ( !found ) {
                    continue;
                }

                index.Add( temp );
                i += s.Length - 1;

            }

            return index.ToArray();
        }

        public static string ConvertUnicodeToAscii ( string unicodeStr, bool skipNonConvertibleChars = false ) {
            if ( string.IsNullOrWhiteSpace( unicodeStr ) ) {
                return unicodeStr;
            }

            var normalizedStr = unicodeStr.Normalize( NormalizationForm.FormD );

            if ( skipNonConvertibleChars ) {
                return new string( normalizedStr.ToCharArray().Where( c => ( int ) c <= 127 ).ToArray() );
            }

            return new string(
                normalizedStr.Where(
                    c => {
                        UnicodeCategory category = CharUnicodeInfo.GetUnicodeCategory( c );
                        return category != UnicodeCategory.NonSpacingMark;
                    } ).ToArray() );
        }



    }



}
